/**
 * JDK 依赖库
 */
import tnx from '@/tnx.js';
import DependencyLib from '../entity/DependencyLib.js';
import BaseType from '../entity/BaseType.js';
import BaseClass from '../entity/BaseClass.js';
import TypeKind from '../enums/TypeKind.js';
import DependencyLibType from '../enums/DependencyLibType.js';
import ParseUtil from './parse.js';

export const STRING_CLASS_NAME = 'java.lang.String';
export const LONG_CLASS_NAME = 'java.lang.Long';
export const INTEGER_CLASS_NAME = 'java.lang.Integer';
export const ENUM_CLASS_NAME = 'java.lang.Enum';
export const MAP_CLASS_NAME = 'java.util.Map';
export const LIST_CLASS_NAME = 'java.util.List';
export const SET_CLASS_NAME = 'java.util.Set';
export const COLLECTION_CLASS_NAME = 'java.util.Collection';

const jdk17Lib = new DependencyLib(DependencyLibType.JAVA);
jdk17Lib.groupId = 'java';
jdk17Lib.artifactId = 'java';
jdk17Lib.version = '17';
jdk17Lib.favoriteClassNames = [STRING_CLASS_NAME, 'long', LONG_CLASS_NAME, 'int', INTEGER_CLASS_NAME, 'boolean',
    MAP_CLASS_NAME, LIST_CLASS_NAME, SET_CLASS_NAME, COLLECTION_CLASS_NAME];
// 加入原生类型
jdk17Lib.pushClass(new BaseType(TypeKind.PRIMITIVE, '', 'boolean'));
jdk17Lib.pushClass(new BaseType(TypeKind.PRIMITIVE, '', 'byte'));
jdk17Lib.pushClass(new BaseType(TypeKind.PRIMITIVE, '', 'char'));
jdk17Lib.pushClass(new BaseType(TypeKind.PRIMITIVE, '', 'double'));
jdk17Lib.pushClass(new BaseType(TypeKind.PRIMITIVE, '', 'float'));
jdk17Lib.pushClass(new BaseType(TypeKind.PRIMITIVE, '', 'int'));
jdk17Lib.pushClass(new BaseType(TypeKind.PRIMITIVE, '', 'long'));
jdk17Lib.pushClass(new BaseType(TypeKind.PRIMITIVE, '', 'short'));
// 加入基础接口
jdk17Lib.pushClass(new BaseClass(TypeKind.INTERFACE, 'java.util', 'List', ['E'], [{typeId: STRING_CLASS_NAME}]));
jdk17Lib.pushClass(new BaseClass(TypeKind.INTERFACE, 'java.util', 'Set', ['E'], [{typeId: STRING_CLASS_NAME}]));
jdk17Lib.pushClass(new BaseClass(TypeKind.INTERFACE, 'java.util', 'Collection', ['E'], [{typeId: STRING_CLASS_NAME}]));
jdk17Lib.pushClass(new BaseClass(TypeKind.INTERFACE, 'java.util', 'Map', ['K', 'V'],
    [{typeId: STRING_CLASS_NAME}, {typeId: 'java.lang.Object'}]));
jdk17Lib.pushClass(new BaseClass(TypeKind.INTERFACE, 'java.io', 'Serializable'));

const jdk11Lib = jdk17Lib.clone();
jdk11Lib.version = '11';

const includedPackageNames = ['java.lang', 'java.io', 'java.nio', 'java.math', 'java.time', 'java.util'];

const root = tnx.app.getRoot();

function getCacheKey(version) {
    return 'jdk-' + version;
}

function libLoad(jdkLib, zipPath, callback) {
    if (jdkLib.initialized) {
        callback(jdkLib);
    } else {
        const cachedJdkLibJson = localStorage.getItem(getCacheKey(jdkLib.version));
        if (cachedJdkLibJson) {
            const cachedJdkLib = tnx.util.string.parseJson(cachedJdkLibJson);
            if (cachedJdkLib) {
                jdkLib = DependencyLib.of(cachedJdkLib);
                callback(jdkLib);
                return;
            }
        }

        ParseUtil.loadByCodeZip(jdkLib, root + zipPath, (packageName, simpleName) => {
            return includedPackageNames.includes(packageName)
                && !simpleName.endsWith('Throwable')
                && !simpleName.endsWith('Exception')
                && !simpleName.endsWith('Error')
                && simpleName !== 'FdLibm';
            // FdLibm类源代码存在解析错误，忽略
        }, () => {
            localStorage.setItem(getCacheKey(jdkLib.version), tnx.util.string.toJson(jdkLib));
            callback(jdkLib);
        });
    }
}

export default {
    load(version, callback, clearCache = false) {
        if (clearCache) {
            localStorage.removeItem(getCacheKey(version));
        }
        if (version === '17') {
            if (clearCache) {
                jdk17Lib.initialized = null;
            }
            libLoad(jdk17Lib, '/resources/jdk-17-src.zip', callback);
        } else if (version === '11') {
            if (clearCache) {
                jdk11Lib.initialized = null;
            }
            libLoad(jdk11Lib, '/resources/jdk-11-src.zip', callback);
        }
    },
};
